package otw.dao.ibatis.base;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.util.Assert;

/**
 * <p>
 * 最顶层的dao层超类，包含了通用的方法。
 * </p>
 * 包括的通用方法如下:<br>
 * <p>
 * insert 插入1条记录
 * </p>
 * <p>
 * selectById 根据主键获得1条记录<br>
 * selectByObject 根据对象获得1条记录<br>
 * </p>
 * <p>
 * updateById 根据id更新1条记录<br>
 * updateByObject 根据 对象 更新1条记录<br>
 * </p>
 * <p>
 * deleteById 根据主键删除1条记录<br>
 * deleteByObject 根据1系列参数删除满足条件的记录<br>
 * </p>
 * <p>
 * selectByMap 根据1系列参数获得满足条件的记录<br>
 * countByMap 根据1系列参数获得满足条件的记录总数<br>
 * </p>
 * 
 * @author space
 * @date Jun 18, 2008 12:06:28 AM
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class IbatisGenericsDao extends SqlMapClientDaoSupport {
	public static final String INSERT = ".insert";

	public static final String SELECT_BY_ID = ".selectById";
	public static final String SELECT_BY_OBJECT = ".selectByObject";

	public static final String UPDATE_BY_ID = ".updateById";
	public static final String UPDATE_BY_OBJECT = ".updateByObject";

	public static final String DELETE_BY_ID = ".deleteById";
	public static final String DELETE_BY_OBJECT = ".deleteByObject";

	public static final String SELECT_BY_MAP = ".selectByMap";
	public static final String COUNT_BY_MAP = ".countByMap";

	public static final String SELECT_ALL = ".selectAll";

	public static final String SELECT_BY_PAGE = ".selectByPage";

	/**
	 * 获得 一个引用指向 SqlMapClientDaoSupport 类的private SqlMapClientTemplate sqlMapClientTemplate 这样可以简化书写，不用每个函数里都写 getSqlMapClientTemplate()
	 */
	protected SqlMapClientTemplate smct = super.getSqlMapClientTemplate();

	/**
	 * @return
	 */
	public SqlMapClientTemplate getSmct() {
		return smct;
	}

	/**
	 * 插入一条记录
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param 要插入的对象
	 * @return 新生成记录的 主键
	 */
	public <T> Object insert(Class<T> entityClass, T t) {
		return smct.insert(entityClass.getName() + INSERT, t);
	}

	/**
	 * 根据主键，查询记录
	 * 
	 * @param <T>
	 *            被操作类的具体类型
	 * @param entityClass
	 *            被操纵的domain类的具体类型
	 * @param id
	 *            传入参数，一般是主键id
	 * @return
	 */
	public <T> T getById(Class<T> entityClass, Integer id) {
		Assert.notNull(id, "id must not be null!");
		return (T) smct.queryForObject(entityClass.getName() + SELECT_BY_ID, id);
	}

	/**
	 * 根据对象查询记录，注意仅仅返回一条记录，因此通常要用传入对象的主键或unique字段作为查询条件
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param t
	 *            传入对象，通常根据该对象的某个或某几个属性查询满足条件的对象
	 * @return
	 */
	public <T> T getByObject(Class<T> entityClass, T t) {
		Assert.notNull(t, "t must not be null!");
		return (T) smct.queryForObject(entityClass.getName() + SELECT_BY_OBJECT, t);
	}

	/**
	 * 更新一条记录，根据主键
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param id
	 *            主键
	 */
	public <T> int updateById(Class<T> entityClass, Serializable id) {
		return smct.update(entityClass.getName() + UPDATE_BY_ID, id);
	}

	/**
	 * 更新一条记录，根据对象
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param t
	 *            新记录，其主键同要被更新的记录
	 */
	public <T> int updateByObject(Class<T> entityClass, T t) {
		return smct.update(entityClass.getName() + UPDATE_BY_OBJECT, t);
	}

	/**
	 * 删除一条记录，根据主键
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param id
	 *            传入参数，是主键id
	 */
	public <T> int deleteById(Class<T> entityClass, Serializable id) {
		Assert.notNull(id, "id must not be null!");
		return smct.delete(entityClass.getName() + DELETE_BY_ID, id);
	}

	/**
	 * 删除一条记录，根据对象
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param t
	 *            传入参数，泛型类型
	 */
	public <T> int deleteByObject(Class<T> entityClass, T t) {
		Assert.notNull(t, "t must not be null!");
		return smct.delete(entityClass.getName() + DELETE_BY_OBJECT, t);
	}

	/**
	 * 根据 Map 中一系列参数 查询
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param map
	 *            各种条件参数
	 * @return
	 */
	public <T> List<T> getByMap(Class<T> entityClass, Map map) {
		return smct.queryForList(entityClass.getName() + SELECT_BY_MAP, map);
	}

	/**
	 * 求满足查询条件的总记录数
	 * 
	 * @param <T>
	 * @param entityClass
	 * @param map
	 *            查询条件
	 * @return
	 */
	public <T> Integer countByMap(Class<T> entityClass, Map map) {
		return (Integer) smct.queryForObject(entityClass.getName() + COUNT_BY_MAP, map);
	}

	/**
	 * 获得所有记录
	 * 
	 * @param <T>
	 * @param entityClass
	 * @return
	 */
	public <T> List<T> getAll(Class<T> entityClass) {
		return (List<T>) smct.queryForList(entityClass.getName() + SELECT_ALL);
	}
}